package net.qiyuesuo.thread;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.qiyuesuo.BaseTestSupport;
import net.qiyuesuo.pojo.FileMeta;
import net.qiyuesuo.utils.RandomUtils;

/**
 * 通过多线程访问同一文件，写数据
 * @author Administrator
 *
 */
public class WriteInfoByThreads extends BaseTestSupport{

	
	public static void main(String[] args) throws InterruptedException {
		// 使用5个线程 存储元数据信息
		int threadNum = 5;
		// 存储50个文件
		int fileNum = 5000;
		ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue();
		//计数器
		CountDownLatch count = new CountDownLatch(threadNum); 
		// 将要存储的元数据信息放入队列
		for (int i = 0; i < fileNum; i++) {
			//模拟存文件
			FileMeta info = new FileMeta(RandomUtils.getRandomFileKey(),222L,new Date());
			queue.offer("文件_" + i+"--- "+ info.toJson());
		}
		//计时
		long start = System.currentTimeMillis();
		// 执行5个线程 从队列中取出元素
		Logger logger = LoggerFactory.getLogger(WriteInfoByThreads.class);
		logger.info("-------------------------开始存储元数据-------------------------");
		ExecutorService service = Executors.newFixedThreadPool(threadNum);
		for(int i=0;i<threadNum ;i++) {
			service.submit(new SaveMetaTask("线程："+i,queue,count));
		}
		//计数器等待，直到队列为空(所有数据存储完)
		count.await();
		long time = System.currentTimeMillis() - start;
		logger.info("-----------------全部存储完成---------------------------");
		logger.info("共耗时:"+time+" ms");
		//停止线程池
		service.shutdown();
	}

	
	private static class SaveMetaTask  implements Runnable{
		
		private String name;
		private ConcurrentLinkedQueue<String> queue;
		private CountDownLatch count;
		private Logger logger = LoggerFactory.getLogger(getClass());
		
		public SaveMetaTask(String name,ConcurrentLinkedQueue queue,CountDownLatch count) {
			this.name = name;
			this.count = count;
			this.queue = queue;
		}
		
		@Override
		public void run() {
			while(!queue.isEmpty()) {
				//从队列中取出一个元素，存储一条数据
				Path path = Paths.get("C:\\Users\\Administrator\\Desktop\\File\\Logs\\metadata.txt");
				try {
					String meta = queue.poll();
					Files.write(path, (meta+"\r\n").getBytes(),StandardOpenOption.APPEND);
					logger.info("【"+meta+"】------已存储-------，使用的线程是："+name);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			count.countDown();//计数器 -1
		}
		
		
	}
	
	
	
}
